/**
 *---------------------------------------------------------------------------------------------------------------------
 *  @copyright Copyright (c) 2022  <dx_65535@163.com>.
 *
 *  @file       : main_unix_stream_server.cc
 *  @author     : Xiang.D (dx_65535@163.com)
 *  @version    : 1.0
 *  @brief      : Blog: https://mp.weixin.qq.com/s/eoCPWMGbIcZyxvJ3dMjQXQ
 *  @date       : 2024/11/22
 *
 *
 *  Change History:
 *  <Date>     | <Version> | <Author>       | <Description>
 *---------------------------------------------------------------------------------------------------------------------
 *  2024/11/24 | 1.0.0.1   | Xiang.D        | Create file
 *---------------------------------------------------------------------------------------------------------------------
 *
 */
#include <list>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include "PSocket.h"
#include "EpollEventHandler.h"

using namespace std;

#define SPR_LOGD(fmt, args...) printf("MainUnStreamSrv D: %4d " fmt, __LINE__, ##args)
#define SPR_LOGW(fmt, args...) printf("MainUnStreamSrv W: %4d " fmt, __LINE__, ##args)
#define SPR_LOGE(fmt, args...) printf("MainUnStreamSrv E: %4d " fmt, __LINE__, ##args)

int main(int argc, char *argv[])
{
    if (argc != 2) {
        SPR_LOGE("Usage: %s <srvPath>\n", argv[0]);
        return -1;
    }

    string srvPath = argv[1];
    std::list<std::shared_ptr<PUnixStreamClient>> clients;
    auto epollHandler = EpollEventHandler::GetInstance();

    auto pUnStreamSrv = make_shared<PUnixStreamServer>([&](int clifd, void* arg) {
        auto pUnStreamSrv = reinterpret_cast<PUnixStreamServer*>(arg);
        if (!pUnStreamSrv) {
            SPR_LOGE("pUnStreamSrv is nullptr\n");
            return;
        }

       auto pUnStreamClient = make_shared<PUnixStreamClient>(clifd, [&](int fd, void* arg) {
            auto pUnStreamClient = reinterpret_cast<PUnixStreamClient*>(arg);
            if (!pUnStreamClient) {
                SPR_LOGE("pUnStreamClient is nullptr\n");
                return;
            }

            std::string bytes;
            int32_t rc = pUnStreamClient->Read(fd, bytes);
            if (rc > 0) {
                SPR_LOGD("# RECV [%d]> %s\n", fd, bytes.c_str());
                std::string sBuf = "Hello, unix client";
                rc = pUnStreamClient->Write(fd, sBuf);
                if (rc > 0) {
                    SPR_LOGD("# SEND [%d]> %s\n", fd, sBuf.c_str());
                }
            }

            if (rc <= 0) {
                clients.remove_if([fd, pUnStreamClient](shared_ptr<PUnixStreamClient>& v) {
                    return (v->GetEvtFd() == fd);
                });
                SPR_LOGD("Del client %d, total = %ld\n", fd, clients.size());
            }
        });

        int rc = pUnStreamClient->AsUnixStreamClient();
        if (rc != -1) {
            clients.push_back(pUnStreamClient);
            SPR_LOGD("Add client %d, total = %ld\n", pUnStreamClient->GetEvtFd(), clients.size());
        }
    });

    int ret = pUnStreamSrv->AsUnixStreamServer(srvPath.c_str(), 5);
    if (ret != -1) {
        SPR_LOGD("As unix stream server success!\n");
    }

    epollHandler->EpollLoop();
    return 0;
}
